1

protobuf是Google开发出来的一个语言无关、平台无关的数据序列化工具,在rpc或tcp通信等很多场景都可以使用。通俗来讲,如果客户端和服务端使用的是不同的语言,那么在服务端定义一个数据结构,通过protobuf转化为字节流,再传送到客户端解码,就可以得到对应的数据结构。这就是protobuf神奇的地方。并且,它的通信效率极高,“一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一”。

安装

  • 编译安装protobuf的编译器protoc

        wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
        tar zxvf protobuf-2.6.1.tar.gz
        cd protobuf-2.6.1./configure
        make
        make install
        执行 protoc  -h 查看安装是否成功
  • 安装插件 protoc-gen-go,它是一个go程序,编译它之后将可执行文件执行路径写入环境变量

        go get github.com/golang/protobuf/protoc-gen-go
  • 获取proto

        go get github.com/golang/protobuf/proto

在go中使用

protobuf的使用方法是将数据结构写入到.proto文件中,使用protoc编译器编译(间接使用了插件)得到一个新的go包,里面包含go中可以使用的数据结构和一些辅助方法。

编写test.proto文件

    package example;
    
    enum FOO { X = 17; };
    
    message Test {
      required string label = 1;
      optional int32 type = 2 [default=77];
      repeated int64 reps = 3;
      optional group OptionalGroup = 4 {
        required string RequiredField = 5;
      }
    }
    编译:
    执行 protoc --go_out=. *.proto 生成 test.pb.go 文件
    将test.pb.go文件放入example文件夹(对应上面package)中,作为example包

try

    package main

    import (
        "log"

        "github.com/golang/protobuf/proto"
        "example"
    )

    func main() {
        test := &example.Test {
            Label: proto.String("hello"),
            Type:  proto.Int32(17),
            Reps:  []int64{1, 2, 3},
            Optionalgroup: &example.Test_OptionalGroup {
                RequiredField: proto.String("good bye"),
            },
        }
        data, err := proto.Marshal(test)
        if err != nil {
            log.Fatal("marshaling error: ", err)
        }
        newTest := &example.Test{}
        err = proto.Unmarshal(data, newTest)
        if err != nil {
            log.Fatal("unmarshaling error: ", err)
        }
        // Now test and newTest contain the same data.
        if test.GetLabel() != newTest.GetLabel() {
            log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
        }
        //test.GetOptionalgroup().GetRequiredField()
        //etc
    }

一些对应关系

  • message Test对为 struct 结构,其属性字段有了对应的get方法,在go中可以使用test.GetLabel()、test.GetType()获取test对象的属性

  • OptionalGroup对应为 struct中的内嵌struct

  • proto文件中repeated属性对于slice结构

  • test.Reset()可以使其所有属性置为0值

  • 使用Marshal和Unmarshal可以轻松的编码和解码

这些只是一些特性,想要仔细研究可以查看github上的wiki:https://github.com/golang/pro...


Dr_Zhang
156 声望20 粉丝

进击的巨人